﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace APP.Win32
{
    public class ScreenInformations
    {
        public static uint RawDpi { get; private set; }

        static ScreenInformations()
        {
            //uint dpiX;
            //uint dpiY;
            //GetDpi(DpiType.RAW, out dpiX, out dpiY);
            //RawDpi = dpiX;
        }

        public static double GetDPIRate(int x, int y)
        {
            GetDpi(DpiType.EFFECTIVE, x, y, out uint dpiX, out uint dpiY);

            switch (dpiX)
            {
                case 96: return 1;
                case 120: return 1.25;
                case 144: return 1.5;
                case 168: return 1.75;
                default:
                    return 1;
            }
        }

        /// <summary>
        /// Returns the scaling of the given screen.
        /// </summary>
        /// <param name="dpiType">The type of dpi that should be given back..</param>
        /// <param name="dpiX">Gives the horizontal scaling back (in dpi).</param>
        /// <param name="dpiY">Gives the vertical scaling back (in dpi).</param>
        public static void GetDpi(DpiType dpiType, int x, int y, out uint dpiX, out uint dpiY)
        {
            var point = new System.Drawing.Point(x, y);
            var hmonitor = MonitorFromPoint(point, _MONITOR_DEFAULTTONEAREST);

            switch (GetDpiForMonitor(hmonitor, dpiType, out dpiX, out dpiY).ToInt32())
            {
                case _S_OK: return;
                case _E_INVALIDARG:
                    throw new ArgumentException("Unknown error. See https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510.aspx for more information.");
                default:
                    throw new COMException("Unknown error. See https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510.aspx for more information.");
            }
        }



        //https://msdn.microsoft.com/en-us/library/windows/desktop/dd145062.aspx
        [DllImport("User32.dll")]
        private static extern IntPtr MonitorFromPoint([In] System.Drawing.Point pt, [In] uint dwFlags);

        //https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510.aspx
        [DllImport("Shcore.dll")]
        private static extern IntPtr GetDpiForMonitor([In] IntPtr hmonitor, [In] DpiType dpiType, [Out] out uint dpiX, [Out] out uint dpiY);

        //IntPtr hwnd = new WindowInteropHelper(this).Handle; //----this就是要获取句柄的窗体的类名；
        //var windpi = ScreenInformations.GetDpiForWindow(hwnd);

        [DllImport("user32.dll")]
        public static extern uint GetDpiForWindow([In] IntPtr hwnd);


        const int _S_OK = 0;
        const int _MONITOR_DEFAULTTONEAREST = 2;
        const int _E_INVALIDARG = -2147024809;
    }

    /// <summary>
    /// Represents the different types of scaling.
    /// </summary>
    /// <seealso cref="https://msdn.microsoft.com/en-us/library/windows/desktop/dn280511.aspx"/>
    public enum DpiType
    {
        EFFECTIVE = 0,
        ANGULAR = 1,
        RAW = 2,
    }


    //[\\.\DISPLAY1] [RAW] xx 54  yy 54
    //[\\.\DISPLAY1] [EFFECTIVE] xx 96  yy 96
    //[\\.\DISPLAY1] [ANGULAR] xx 54  yy 54
    //[\\.\DISPLAY8] [RAW] xx 81  yy 81
    //[\\.\DISPLAY8] [EFFECTIVE] xx 96  yy 96
    //[\\.\DISPLAY8] [ANGULAR] xx 81  yy 81
    //100 150   1.77

    //[\\.\DISPLAY1] [RAW] xx 68  yy 68
    //[\\.\DISPLAY1] [EFFECTIVE] xx 120  yy 120
    //[\\.\DISPLAY1] [ANGULAR] xx 68  yy 68
    //[\\.\DISPLAY8] [RAW] xx 81  yy 81
    //[\\.\DISPLAY8] [EFFECTIVE] xx 120  yy 120
    //[\\.\DISPLAY8] [ANGULAR] xx 81  yy 81
    //125 150   1.76

    //[\\.\DISPLAY1] [RAW] xx 81  yy 81
    //[\\.\DISPLAY1] [EFFECTIVE] xx 144  yy 144
    //[\\.\DISPLAY1] [ANGULAR] xx 81  yy 81
    //[\\.\DISPLAY8] [RAW] xx 81  yy 81
    //[\\.\DISPLAY8] [EFFECTIVE] xx 144  yy 144
    //[\\.\DISPLAY8] [ANGULAR] xx 81  yy 81
    //150 150 1.777


    //[\\.\DISPLAY1] [RAW] xx 95  yy 95
    //[\\.\DISPLAY1] [EFFECTIVE] xx 168  yy 168
    //[\\.\DISPLAY1] [ANGULAR] xx 95  yy 95
    //[\\.\DISPLAY8] [RAW] xx 81  yy 81
    //[\\.\DISPLAY8] [EFFECTIVE] xx 168  yy 168
    //[\\.\DISPLAY8] [ANGULAR] xx 81  yy 81
    //175 150
}
